/**
 * new 的执行过程
 * 1. 创建一个对象obj
 * 2. 该对象的__proto__指向构造函数Fn的原型prototype
 * 3. 执行构造函数Fn的代码，往新创建的对象obj上添加成员属性和方法
 * 4. 返回这个新的对象obj
 */

const _new = function (func, ...args) {
  if (typeof func !== 'function') {
    throw 'func must be a function'
  }
  // 这里有点求快了，应该手动模拟一下
  let obj = Object.create(func.prototype)
  // let obj1 = new Object()
  // Object.setPrototypeOf(obj, func.prototype) 
  /**
    准确的说应该时这样：
    1. 创建空对象；
    2. 对象的【原型指针，__proto__】指向构造函数的【原型属性，function.prototype】；
    3. this指向这个空对象，并执行构造函数；
    4. 如果构造函数返回非 基本类型（也叫原始值），则该返回值成为整个 new 表达式的结果。否则，如果构造函数未返回任何值或返回了一个基本类型，则返回之前创建的对象。
   * 
   * **/
  // 实际模拟如下
  /** Ctor 构造函数
  let Ctor = function () {}

  Ctor.prototype = func.prototype
  Ctor.prototype.constructor = func

  let obj = new Ctor()
 */
  let result = func.apply(obj, args)

  // @bug 基础类型包括了null，所以这里 result !== null多余了
  if (typeof result === 'object' && result !== null || typeof result === 'function') {
    return result
  } else {
    return obj
  }
}

let Person = function (name, sex) {
  this.name = name
  this.sex = sex
}

Person.prototype.showInfo = function () {
  console.log(this.name, this.sex)
}

let p1 = _new(Person, '前端胖头鱼', 'sex')

console.log(p1)

